#ifndef ___J2MEFXION___
#define ___J2MEFXION___

#include "jSocket.h"

class HTTP_POST
{
private:
	AStr r;
	AStr c;
public:

	~HTTP_POST()
	{
		r.clear();
		c.clear();
	}
	HTTP_POST()	{ Init(); }
	void Init()
	{
		r.clear();
		c.clear();
	}
	void Add(const AStr& Type, const AStr& Content)
	{
		r += Type + " " + Content + "\r\n";
	}
	void AddData(const AStr& Content)
	{
		c = Content;
		r += jPrintf("Content-Length: %d\r\n",Content.len());
	}
	AStr Get()
	{
		AStr x = r + "\r\n" + c;
		return x;
	}
};

class J2MESocket
{
private:
	AStr Host;
	jSocket js;
	HTTP_POST r;
	AStr res;

	#define BufLen 16
	AStr RcvQuene[BufLen];
	int ro,ri;

	AStr SndQuene[BufLen];
	int so,si;

	bool ThreadFlag;
	HANDLE hThread;


public:
	
	void Init()
	{
		ThreadFlag = false;
		ro = ri = 0;
		so = si = 0;
	}

	bool Init(AStr ap)
	{
		Init();
		Host = ap;
		return js.Init(ap);
	}
	
	J2MESocket(AStr ap)		{ Init(ap); }
	J2MESocket()			{ Init(); }
	~J2MESocket()			{ js.Close(); }

	void ThreadExit()		{ ThreadFlag = false; }
	bool SocketError()		{ return (js.s == -1); }
	bool GetStatus()		{ return ThreadFlag; }

	static DWORD WINAPI RcvThread(LPVOID p)
	{
		J2MESocket* jx = (J2MESocket*)p;
		AStr res,r;
		DWORD Tick = GetTickCount();
		int i;
		if (GetReg(L"debug"))
			Debug("Enter J2ME Socket Thread!\n\n");

		jx->ThreadFlag = true;
		while(jx->ThreadFlag)
		{
			Sleep(100);

			r = jx->js.Read();

			if (GetTickCount()-Tick>300000) 
			{
				jx->js.Close();
				break; //5 minutes not recieve any data means socket error
			}
			if (jx->SocketError()) 
			{
				jx->js.Close();
				break;	//Socket error exit!
			}

			if (r.isne())
			{
				Tick = GetTickCount();
				res.assign(r,r.len(),true);
				i = res.len()>2 ? TOWORD((BYTE)res[0],(BYTE)res[1]):-1;
				while (i!=-1 && res.len()>=i)
				{
					if (jx->ro==jx->ri || ((BufLen+jx->ro-jx->ri) % BufLen))
					{
						jx->RcvQuene[jx->ri<BufLen?jx->ri++:jx->ri=0].assign(res,i,false);
						res = res.mid(i);
					}
					i = res.len()>2 ? TOWORD((BYTE)res[0],(BYTE)res[1]):-1;
				}
			}

			if (jx->si != jx->so)
			{
				jx->Write(jx->SndQuene[jx->so<BufLen?jx->so++:jx->so=0]);
			}
		}

		jx->ThreadFlag = false;
		jx->js.Close();

		if (GetReg(L"debug"))
			Debug("Leave J2ME Socket Thread!\n\n");

		return 0;
	}

	bool Thread()
	{
		if (ThreadFlag) return true;
		DWORD dwThread;
		hThread = CreateThread(NULL,0,RcvThread,this,0,&dwThread);
		return hThread!=NULL;		
	}
	
	AStr Read()
	{
		if (ro==ri) return "";
		return RcvQuene[ro<BufLen?ro++:ro=0];
	}

	bool Send(const AStr& s)
	{
		SndQuene[si<BufLen?si++:si=0].assign(s,s.len(),false);
		return true;
	}

	AStr Request(const AStr& r)
	{
		if (js.Write(r))
		{
			//while(!js.Test(2000));
			res.clear();
			int i,cnt=0;
			do
			{
				res += js.Read();
				i = TOWORD(B(res[0]),B(res[1]));
				if (res.len()>=i) return res;
				cnt++;
				Sleep(100);
			}while(cnt<300);
		}
		return res;
	}

	bool Write(const AStr& s)
	{
		return js.Write(s);
	}
	
	AStr SourceIP()			{ return js.SourceIP(); }
	AStr DestinationIP()	{ return js.DestinationIP(); }

	bool InitJ2MESocket(const AStr& ap)
	{
		js.Close();
		if (Init(ap))
		{
			return Thread();
		}
		return false;
	}

	AStr POST(const AStr& Url, const AStr& Data)
	{
		AStr url = Url;
		if (Init("10.0.0.172:80"))
		{
			AStr xHost = url.get("//","/");
			AStr Path = url.mid(*xHost);
			r.Init();	
			r.Add("POST",Path+" HTTP/1.1");
			r.Add("Content-Type:","text/xml");
			r.Add("X-Online-Host:",xHost);
			r.Add("Host:",Host);

			r.AddData(Data);

			if (js.Write(r.Get()))
			{
				//while(!js.Test(2000));
				res.clear();
				AStr r;
				int i,j,cnt=0;
				do
				{
					r = js.Read();
					res.assign(r,r.len(),true);
					j = res.find("\r\n\r\n");
					if (j!=-1) 
					{
						j+=4;
						i=res.get("Content-Length:","\r\n").trim(" ").toi();
						if (i+j<=res.len())
						{
							js.Close();
							/*if (GetReg(L"debug"))
								WriteFile("\\log.txt",res);
							*/
							return res.mid(j,i);
						}
					}
					cnt++;
					Sleep(100);
				}while(cnt<100);
			}
			return res;

		}
		return "";
	}
};

#endif
